// File:			R3.cpp
// Authors:			Richard Burris, Joshua Douty
// Purpose:			R3 work file
// Version:        	6.0
// Date:			11/03/2011


#include "mpx_supt.h"
//#include "R1.h"
#include "R2.h"
#include "R3.h"
//#include "R4.h"
#include "R6.h"
//#include "COMHAND.h"

unsigned short ss_save = NULL;
unsigned short sp_save = NULL;
unsigned short new_ss = NULL;
unsigned short new_sp = NULL;

//unsigned char sys_stack[SYS_STACK_SIZE];  //SYS_STACK_SIZE is 1024
unsigned char* sys_stack = NULL;

//Queues from Module R2;
extern PCB_Pointer CurrOP;
extern PCB_Pointer Ready;
extern PCB_Pointer Blocked;
extern PCB_Pointer SuspBlocked;
extern PCB_Pointer SuspReady;


context_Pointer thecont;
params *param_ptr;

/*	Procedure:  r3_init
	Purpose: initializes some PCB values
	Parameters:	void
	Return value: void
	Calls: 	void
	Globals: none
	Errors: none
*/
void R3_init(void){
	ss_save = NULL;
	sp_save = NULL;
	new_ss = NULL;
	new_sp = NULL;
}//end R3_init



/*	Procedure:  sys_call
	Purpose: Determines if a process wants to terminate at the end of its CPU time or moved to Ready queue
	Parameters:	void
	Return value: void 
	Calls: 	insertReady
			dispatch
			deletePCB2
	Globals: none
	Errors: none
*/
void interrupt sys_call(void){
	//access the stack and get the parameters
	param_ptr = (struct params*)(CurrOP->sTop+ (sizeof(struct context)));
	//param_ptr = ((unsigned char*)MK_FP(_SS,_SP) + (sizeof(context)));
	CurrOP->sTop=(unsigned char*)MK_FP(_SS,_SP);
	new_ss = FP_SEG(sys_stack);//switch to temporary stack
	new_sp = FP_OFF(sys_stack);
	new_sp +=SYS_STACK_SIZE;
	_SS = new_ss;
	_SP = new_sp;
	thecont = (context_Pointer)CurrOP->sTop;

	//trm_getc();
//look in terminal for an IO request
/*************
if(termQ->event_flag ==1){
	termQ->event_flag = 0;
	temp = termQ->head;
	termQ->head = temp->next;
	
	
}//end if ternQ		


*******/

/***************
	if(comQ->event_flag ==1){
		comQ->event_flag = 0;
		temp = comQ->head;
		comQ->head = temp->next;
		if(comQ->head != NULL){
			if (temp->rType ==READ){
				com_read(temp->tBuff, temp->cBuff);
			}
			if(temp->rType == WRITE){
				com_write(temp->tBuff, temp->cBuff);
			}
		}//end if comQ->head
	}
	
********/
	//check the parameters(use a SWITCH statement)
	if (param_ptr->op_code == IDLE){
		//process wants to continue executing
		CurrOP->stateR = READY;//set CurrOP state to ready
		insertReady(CurrOP);//insert CurrOP into the ready queue, in priority order
	}//end if
	else if (param_ptr->op_code == EXIT){
		//process wants to terminate
		//char* thename = CurrOP->name;//pull the name from CurrOP 
		deletePCB2(CurrOP);//delete CurrOP, and be sure to free its memory
		//CurrOP = NULL;//set CurrOP to NULL
	}//end if
	
	/****************
	
	else if( param_ptr->op_code == READ){
		//run the IO scheduler
		break;
	}else if(param_ptrr->op_code ==WRITE){
		//run the IO scheduler
		break;
	}else if(param_ptr->op_code==CLEAR){
		//run the IO scheduler
		break;
	}else if(param_ptr->op_code==GOTOXY){
		//run the IO scheduler
		break;
	}//end else
	
	****************/
		
	//call the dispatcher
	thecont->AX = OK;
	CurrOP = NULL;
	dispatch();
}//end sys_call




/*	Procedure:  dispatch
	Purpose: switches out PCBs
	Parameters:	void
	Return value: void
	Calls: 	removePCB			
	Globals: none
	Errors: none
*/
void interrupt dispatch(void){
	if(ss_save == NULL){
		ss_save = _SS;
		sp_save = _SP;


	}//end if
	CurrOP = Ready;
	if(Ready!= NULL){		//if there are processes in the ready queue

		removePCB(CurrOP);//remove it from the ready queue
		CurrOP->stateR = RUN; //set it to run
		new_ss =FP_SEG(CurrOP->sTop); //grab SS and SP
		new_sp = FP_OFF(CurrOP->sTop);
		_SS = new_ss;//set ss of the processor to ss of the PCB's context
		_SP = new_sp;//set sp of the processor to sp of the PCB's context	
	} else{
		CurrOP = NULL;	//ensure that the CurrOP is NULL
		//restore ss and sp
		_SS = ss_save;
		_SP = sp_save;
		sp_save = NULL;
		ss_save = NULL;
	}//end if structure  

	//return from the interrupt
}//end dispatch



/*	Procedure:  loadCOMHAN
	Purpose: loads the comhan process from a text file
	Parameters:	char arg: determines whether to find the helpfile, or to run the command
	Return value: void
	Calls: createPCB2
	Globals: none
	Errors: none
*/

/*
void loadCOMHAN(){
	if(sys_stack ==NULL){
			sys_stack = (unsigned char*)(sys_alloc_mem(STACKSIZE*sizeof(unsigned char)));
	}
	PCB_Pointer comhan_p = NULL;
	context_Pointer comhan_c = NULL;
	char* name1 = "COMHAN";
		int class1 = SYSTEM;
		int prio1 = 127;
		comhan_p = createPCB2(name1, class1, prio1);//creates the PCB, initializes all the 
		comhan_c = (context*)comhan_p->sTop;
		comhan_c->IP=FP_OFF(&comhander);
		comhan_c->CS = FP_SEG(&comhander);
		comhan_c->FLAGS = 0x200;
		comhan_c->DS = _DS;
		comhan_c->ES = _ES;
}//end loadCOMHAN
*/
/*

void loadProcess(char arg){
	if (arg == '?'){
		readHelp("load.txt");
	} else{
		if(sys_stack ==NULL){
			sys_stack = (unsigned char*)(sys_alloc_mem(STACKSIZE*sizeof(unsigned char)));
		}
		PCB_Pointer np1 = NULL;
		PCB_Pointer np2 = NULL;
		PCB_Pointer np3 = NULL;
		PCB_Pointer np4 = NULL;
		PCB_Pointer np5 = NULL;
		context_Pointer npc1 = NULL;
		context_Pointer npc2 = NULL;
		context_Pointer npc3 = NULL;
		context_Pointer npc4 = NULL;
		context_Pointer npc5 = NULL;

		//test1_R3
		char* name1 = "test1_R3";
		int class1 = APPLICATION;
		int prio1 = 0;
		np1 = createPCB2(name1, class1, prio1);//creates the PCB, initializes all the 
		npc1 = (context*)np1->sTop;
		npc1->IP=FP_OFF(&test1_R3);
		npc1->CS = FP_SEG(&test1_R3);
		npc1->FLAGS = 0x200;
		npc1->DS = _DS;
		npc1->ES = _ES;

		//test2_R3
		char* name2 = NULL;
		name2 = "test2_R3";
		int class2 = APPLICATION;
		int prio2 = 0;
		np2 = createPCB2(name2, class2, prio2);
		npc2 = (context*)np2->sTop;
		npc2->IP=FP_OFF(&test2_R3);
		npc2->CS = FP_SEG(&test2_R3);
		npc2->FLAGS = 0x200;
		npc2->DS = _DS;
		npc2->ES = _ES;

		//test3_R3
		char* name3 = NULL;
		name3 = "test3_R3";
		int class3 = APPLICATION;
		int prio3 = 0;
		np3 = createPCB2(name3, class3, prio3);
		npc3 = (context*)np3->sTop;
		npc3->IP=FP_OFF(&test3_R3); 
		npc3->CS = FP_SEG(&test3_R3);
		npc3->FLAGS = 0x200;
		npc3->DS = _DS;
		npc3->ES = _ES;

		//test4_R3
		char* name4 = NULL;
		name4 = "test4_R3";
		int class4 = APPLICATION;
		int prio4 = 0;
		np4 = createPCB2(name4, class4, prio4);
		npc4 = (context*)np4->sTop;
		npc4->IP=FP_OFF(&test4_R3);
		npc4->CS = FP_SEG(&test4_R3);
		npc4->FLAGS = 0x200;
		npc4->DS = _DS;
		npc4->ES = _ES;

		//test5_R3
		char* name5 = NULL;
		name5 = "test5_R3";
		int class5 = APPLICATION;
		int prio5 = 0;
		np5 = createPCB2(name5, class5, prio5);
		npc5 = (context*)np5->sTop;
		npc5->IP=FP_OFF(&test5_R3);
		npc5->CS = FP_SEG(&test5_R3);
		npc5->FLAGS = 0x200;
		npc5->DS = _DS;
		npc5->ES = _ES;
	}
}

*/



/*	Procedure:  calldispatch
	Purpose: Calls the dispatch interrupt
	Parameters:	char arg: determines whether to find the helpfile, or to run the command
	Return value: void
	Calls: 	readHelp 
			dispatch
	Globals: none
	Errors: none
*/
void calldispatch(char arg){
	if (arg == '?') {
		readHelp("dispatch.txt");
	}
	else if(Ready == NULL){
		printf("/n Processes are finished");
		} 
		else{
			dispatch();
		}//end else
}//end calldispatch